package xworker.lang;

import org.xmeta.ActionContext;
import org.xmeta.Thing;
import org.xmeta.cache.ThingObjectEntry;
import org.xmeta.util.ThingClassLoader;
import xworker.lang.executor.Executor;

import java.io.File;
import java.net.URL;
import java.util.List;

public class ClassLoaderActions {
	private static final String TAG = ClassLoaderActions.class.getName();

	public static ClassLoader getClassLoader(ActionContext actionContext) {
		Thing self = actionContext.getObject("self");
		
		String key = "ClassLoader";
		ThingObjectEntry<ThingClassLoader> entry = self.getStaticData(key);
		if(entry == null){
			entry = new ThingObjectEntry<ThingClassLoader>(self) {
				final ActionContext context = actionContext;

				@Override
				protected ThingClassLoader createObject(Thing thing) {
					ClassLoader parent = thing.doAction("getParentClassLoader", context);
					List<String> classPaths = thing.doAction("getClassPaths", context);

					ThingClassLoader classLoader;
					if(classPaths != null && classPaths.size() > 0) {
						URL[] urls = new URL[classPaths.size()];
						for(int i=0; i<classPaths.size(); i++) {
							try {
								urls[i] = new File(classPaths.get(i)).toURI().toURL();
							}catch(Exception e){
								Executor.warn(TAG, "Init url exception, " + classPaths.get(i), e);
							}
						}

						if(parent == null) {
							classLoader = new ThingClassLoader(urls);
						}else {
							classLoader = new ThingClassLoader(urls, thing.getMetadata().getThingManager().getClassLoader());
						}
					}else {
						if(parent == null) {
							classLoader = new ThingClassLoader(new URL[] {});
						}else {
							classLoader = new ThingClassLoader(new URL[] {}, thing.getMetadata().getThingManager().getClassLoader());
						}
					}

					for(Thing child : thing.getChilds()) {
						Executor.info(TAG, "Init child, path=" + child.getMetadata().getPath());
						child.doAction("run", context, "classLoader", classLoader);
					}
					return null;
				}
			};

			self.setStaticData(key, entry);
		}

		return entry.getObject();
	}
	
	public static void clearClassLoader(ActionContext actionContext) {
		Thing self = actionContext.getObject("self");
		
		self.setStaticData("ClassLoader", null);
	}

	//xworker.java.lang.ClassLoader/@AddJars/@actions/@run
	public static void addJars(ActionContext actionContext){
		Thing self = actionContext.getObject("self");

		File directory = self.doAction("getDirectory", actionContext);
		if(directory == null){
			Executor.warn(TAG, "Can not add jars, directory is null, path=" + self.getMetadata().getPath());
		}else{
			ThingClassLoader classLoader = actionContext.getObject("classLoader");
			classLoader.addJarOrZip(directory);
		}
	}
}
